<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>生成九宫格图片</title>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
		<script type="text/javascript" src="https://gitcode.net/dcloud/uni-app/-/raw/dev/dist/uni.webview.1.5.6.js">
		</script>
		<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"> -->
		<style>
			* {
				box-sizing: border-box;
				padding: 0;
				margin: 0;
				-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
			}

			#my-canvas {
				width: 1000px;
				height: 1000px;
				border: 1px solid black;
				position: absolute;
				right: 1000%;
			}

			.imgs-list {
				display: flex;
				flex-wrap: wrap;
				width: 308px;
				height: 308px;
				margin-top: 40px;
				position: relative;
				line-height: 0;
				cursor: pointer;
				--store-width: 4px;
			}

			.imgs-list-bg {
				position: absolute;
				z-index: -1;
				left: 0;
				top: 0;
				width: 100%;
				height: 100%;
				opacity: 0.8;
				filter: blur(16px);
			}

			.imgs-list.loading {
				background-color: #f7f7f7;
				border-radius: 8px;

			}

			.imgs-list.loading::before {
				content: "☞点我选择图片☜";
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
				max-width: 100%;
				text-align: center;
				color: #666;
				font-size: 14px;
				white-space: pre-line;
			}

			.imgs-list-item {
				width: 100px;
				height: 100px;
				line-height: 1;
				font-size: 0;
				vertical-align: top;
				margin-left: var(--store-width);
				border-radius: 3px;

			}

			.imgs-list-item:nth-of-type(n+4) {
				margin-top: var(--store-width);
			}

			.imgs-list-item:nth-of-type(3n+1) {
				margin-left: 0px;
			}


			#upload {
				display: none;
			}

			.choose-image {
				background-color: #07C160;
				color: #fff;
				font-size: 14px;
				margin-top: 20px;
				line-height: 40px;
				border-radius: 20px;
				height: 20rpx;
				align-self: center;
				text-align: center;
				width: 120px;
				display: none;
				cursor: pointer;
				user-select: none;
				transition: all 0.2s;
			}

			.choose-image:active {
				opacity: 0.9;
			}

			.choose-image:hover {
				opacity: 0.9;
			}

			#desc-text {
				color: #999;
				margin-top: 10px;
				font-size: 14px;
				display: none;
			}

			.style-1 {
				display: block;
				background-color: #F7F7F7;
				color: #666;
			}
		</style>
	</head>

	<body>
		<div style="width: 100vw;display: flex;flex-direction: column;align-items: center;user-select: none;">
			<div class="imgs-list loading" onclick="chooseImage()">
				<!-- 背景 -->
				<!-- 背景 -->
			</div>


			<div draggable="false"
				style="position: relative;margin-top: 10px;overflow: hidden;border-radius: 4px;cursor: pointer;user-select: none;"
				id="preview-box">
				<img draggable="false" src="" id="preview"
					style="opacity: 0.8;line-height: 0;vertical-align: top;font-size: 0;">
				<div draggable="false" class="kuangkuang"
					style="width: 80px;height: 80px;position: absolute;left:50%;top: 50%;transform: translate(-50%,-50%);background-color: rgba(0,0,0,0.5);border: 1px dashed #FFF;border-radius: 4px;margin-top:0;margin-left: 0;">
				</div>
			</div>

			<div id="desc-text">点击或者长按单张图片可下载/保存<span style="padding-left: 4px;color:#07C160;"
					onclick="editWidth()">修改间隙</span></div>
			<div style="display: flex;">
				<div class="choose-image style-1" onclick="chooseImage()">选择图片
				</div>
				<div id="save-btn" class="choose-image" style="margin-left: 10px;">保存图片</div>
			</div>
			<!-- 隐藏元素 -->
			<input type="file" id="upload" accept="image/*">
			<canvas id="my-canvas"></canvas>
			<!-- 隐藏元素 -->
		</div>

		<script>
			let cha = 0;
			let leftCha = 0;
			let topCha = 0;
			let aspectRatio = 1;
			const saveBtn = document.getElementById('save-btn');
			let imageParts = [];
			const canvas = document.getElementById('my-canvas');
			let file = null;
			let storeWidht = 4;
			const ctx = canvas.getContext('2d');
			document.getElementById('upload').addEventListener('change', function(event) {
				file = event.target.files[0];
				if (!file) return;
				drawImageHandler();

			});

			function drawImageHandler(refresh = false) {
				console.log('drawImageHandler');
				const reader = new FileReader();
				reader.onload = function(e) {
					const img = new Image();
					img.onload = function() {


						let minWidth = Math.min(img.width, img.height);
						let maxWidth = Math.max(img.width, img.height);


						aspectRatio = img.width / img.height;

						if (minWidth >= 1500) {
							minWidth = 1500;
						}
						canvas.width = minWidth;
						canvas.height = minWidth;


						let drawWidth, drawHeight;
						drawWidth = minWidth;
						drawHeight = minWidth / aspectRatio;

						if (aspectRatio > 1) {
							drawWidth = drawWidth * aspectRatio;
							drawHeight = drawHeight * aspectRatio;
						}

						if (!refresh) {
							marginTop = 0;
							marginLeft = 0;
							kuangkuang.style.marginTop = 0;
							kuangkuang.style.marginLeft = 0;
							cha = Math.abs(drawWidth - drawHeight);
							leftCha = 0;
							topCha = 0;

							preview.src = img.src;
							preview.style.width = 80 + 'px';
							preview.style.height = 80 / aspectRatio + 'px';
							if (aspectRatio > 1) {
								preview.style.width = 80 * aspectRatio + 'px';
								preview.style.height = 80 + 'px';
							}
						}



						ctx.clearRect(0, 0, canvas.width, canvas.height);
						ctx.drawImage(img, (canvas.width - drawWidth) / 2 + leftCha, (canvas.height - drawHeight) / 2 +
							topCha, drawWidth, drawHeight);


						const imgsList = document.querySelector('.imgs-list');
						imgsList.innerHTML = '';
						saveBtn.style.display = 'none';
						imgsList.classList.add('loading');

						imageParts = [];
						//定义分割线宽度

						for (let row = 0; row < 3; row++) {
							for (let col = 0; col < 3; col++) {

								let relaseStoreWIdth = (storeWidht) / (300 + storeWidht * 2) * minWidth;

								const tempCanvas = document.createElement('canvas');
								tempCanvas.width = (minWidth - 2 * relaseStoreWIdth) / 3;
								tempCanvas.height = (minWidth - 2 * relaseStoreWIdth) / 3;
								const tempCtx = tempCanvas.getContext('2d');

								tempCtx.drawImage(canvas, col * tempCanvas.width + (relaseStoreWIdth * col), row *
									tempCanvas.height + (relaseStoreWIdth * row), tempCanvas.width, tempCanvas
									.height, 0, 0, tempCanvas.width, tempCanvas.height);

								const partImg = document.createElement('img');
								partImg.className = 'imgs-list-item';
								partImg.src = tempCanvas.toDataURL();
								imageParts.push({
									data: tempCanvas.toDataURL(),
									filename: `${row * 3 + col + 1}-${new Date().getTime()}.png`
								});
								imgsList.appendChild(partImg);

							}
						}
						let imgsListBG = document.createElement('div');
						imgsListBG.className = 'imgs-list-bg';

						imgsListBG.style.background = `url(${canvas.toDataURL()}) left top / 100% 100% no-repeat`;
						imgsList.appendChild(imgsListBG);
						document.querySelector('#desc-text').style.display = 'block';
						saveBtn.style.display = 'block';
						imgsList.classList.remove('loading');
						document.querySelectorAll('.imgs-list-item').forEach((img, index) => {
							img.addEventListener('click', function(event) {
								event.stopPropagation()
								const link = document.createElement('a');
								link.href = this.src;
								link.download = `图${index + 1}`;
								link.click();
							});
						});
					};
					img.src = e.target.result;
				};
				reader.readAsDataURL(file);
			}
		</script>

		<!-- 保存图片 -->

		<script>
			function chooseImage() {
				document.getElementById('upload').click();
			}



			saveBtn.onclick = function() {
				if (uni) {
					appSave();
					return ;
				}

				const zip = new JSZip();
				// const folder = zip.folder("九宫格图");
				if (imageParts.length === 0) {
					return alert('请先选择图片');
				}
				imageParts.forEach(part => {
					// folder.file(part.filename, part.data.split("base64,")[1], { base64: true });
					zip.file(part.filename, part.data.split("base64,")[1], {
						base64: true
					});
				});
				zip.generateAsync({
					type: "blob"
				}).then(function(content) {
					saveAs(content, `九宫格图-${new Date().getTime()}.zip`);
				});
			};
		</script>
		<!-- 保存图片 -->

		<script>
			function isMobileDevice() {
				const userAgent = navigator.userAgent || navigator.vendor || window.opera;

				// 检查常见的移动设备标识符
				if (/android/i.test(userAgent)) {
					return true;
				}

				if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
					return true;
				}

				if (/windows phone/i.test(userAgent)) {
					return true;
				}

				if (/mobile/i.test(userAgent)) {
					return true;
				}

				return false;
			}
		</script>
		<script>
			let lastTouchX = null;
			let lastTouchY = null;
			let kuangkuang = document.querySelector('.kuangkuang');
			let previewBox = document.querySelector('#preview-box');
			let isStartMove = false;
			previewBox.addEventListener('touchmove', touchMove);
			previewBox.addEventListener('touchend', touchEnd);
			previewBox.addEventListener("mousemove", touchMove);
			previewBox.addEventListener('mouseup', touchEnd);
			previewBox.addEventListener('mousedown', () => {
				lastTouchX = event.pageX;
				lastTouchY = event.pageY;
				isStartMove = true;
			});


			let marginTop = 0;
			let marginLeft = 0;

			function touchMove(event) {
				if (!isMobileDevice() && !isStartMove) {
					return;
				}
				// console.log(event);
				//阻止事件冒泡
				event.preventDefault();

				if (lastTouchX === null) {
					if (isMobileDevice()) {

						lastTouchX = event.changedTouches[0].pageX;
						lastTouchY = event.changedTouches[0].pageY;
					} else {

						lastTouchX = event.pageX;
						lastTouchY = event.pageY;

					}


					return;
				}

				//根据位移量修改
				let x, y;
				if (isMobileDevice()) {
					x = event.changedTouches[0].pageX - lastTouchX;
					y = event.changedTouches[0].pageY - lastTouchY;
				} else {
					x = event.pageX - lastTouchX;
					y = event.pageY - lastTouchY;
				}

				let slace = 1;
				let width = Math.max(previewBox.clientWidth, previewBox.clientHeight);

				if (aspectRatio > 1) {
					marginLeft = marginLeft + x;
					if (Math.abs(marginLeft) > (width - 80) / 2) {
						marginLeft = Math.abs(marginLeft) / marginLeft * (width - 80) / 2;
					}
					kuangkuang.style.marginLeft = marginLeft + 'px';
				} else {
					marginTop = marginTop + y;
					if (Math.abs(marginTop) > (width - 80) / 2) {
						marginTop = Math.abs(marginTop) / marginTop * (width - 80) / 2;
					}
					kuangkuang.style.marginTop = marginTop + 'px';

				}
				if (isMobileDevice()) {
					lastTouchX = event.changedTouches[0].pageX;
					lastTouchY = event.changedTouches[0].pageY;
				} else {
					lastTouchX = event.pageX;
					lastTouchY = event.pageY;
				}





				//根据aspectRatio 计算移动的距离
				if (aspectRatio > 1) {
					if (Math.abs(marginLeft) === 0) return;
					leftCha = Math.abs(marginLeft) / marginLeft * cha * (Math.abs(marginLeft) / ((width - 80))) * -1;
				} else {
					if (Math.abs(marginTop) === 0) return;
					topCha = Math.abs(marginTop) / marginTop * cha * (Math.abs(marginTop) / ((width - 80))) * -1;
				}

			}

			function touchEnd(event) {
				lastTouchX = null;
				lastTouchY = null;
				isStartMove = false;
				if (isMobileDevice()) {
					drawImageHandler(true);
				} else {
					drawImageHandler(true);
				}
			}

			function editWidth() {
				var width = prompt("请输入图片间隙", storeWidht);
				width = parseInt(width || storeWidht);
				if (!(width >= 0)) {
					width = 4;
				}
				storeWidht = width;
				let imgsList = document.querySelector('.imgs-list');
				imgsList.style.width = `${300 + 2 * width}px`;
				imgsList.style.height = `${300 + 2 * width}px`;
				imgsList.style.setProperty('--store-width', `${width}px`);
				drawImageHandler(true);

			}
			// editWidth();

			function appSave() {
				if (this.downLoadLoading) return;
				this.downLoadLoading = true;

				uni.postMessage({
					data: {
						action: 'downLoad',
						url: imageParts.map(v => v.data),
					}
				});


			}
		</script>
	</body>

</html>